<template>
  <div class="canvasParabola" @touchstart="move" @touchmove="move">
    <canvas id="parabola" ref="parabolaRef" :width="rect?.width" :height="rect?.height"></canvas>
  </div>
</template>

<script lang="ts">
import { Vue, Options } from 'vue-property-decorator';
interface Pos{
  x: number,
  y: number
}
class Box {
  public current: Pos ={ x: 0, y: 0 };
  public vel: Pos = { x: 0, y: 0 };
  public acl: Pos= { x: 0, y: 0 };
  public aclTo: Pos = { x: 0, y: 0 };
  public color = `#${
    Math.floor((Math.random() * 256)).toString(16)}${
    Math.floor((Math.random() * 256)).toString(16)}${
    Math.floor((Math.random() * 256)).toString(16)}`;
  public alpha = 1;

  constructor(x: number, y: number, ctx: CanvasRenderingContext2D|null) {
    this.current.x = x;
    this.current.y = y;
    const angleVel = Math.random() * 2 * Math.PI;
    const vel = Math.random();
    this.vel.x = vel * Math.cos(angleVel);
    this.vel.y = vel * Math.sin(angleVel);
    this.render(ctx);
  }
  public render(ctx: CanvasRenderingContext2D|null) {
    this.updateAcl();
    this.updatePos();
    ctx!.beginPath();
    ctx!.save();
    ctx?.translate(this.current.x, this.current.y);
    ctx?.rotate(Math.atan2(this.vel.y, this.vel.x));
    this.alpha -= 0.02;
    if (this.alpha < 0) {
      this.alpha = 0;
      this.remove();
    }
    ctx!.globalAlpha = this.alpha;
    ctx!.fillStyle = this.color;
    ctx!.fillRect(-1.5, -1.5, 3, 3);
    ctx!.restore();
  };
  public updateAcl() {
    const angleAcl = Math.random() * 2 * Math.PI;
    const aclNum = Math.random() * 2;
    this.aclTo.x = aclNum * Math.cos(angleAcl);
    this.aclTo.y = aclNum * Math.sin(angleAcl);
    this.acl.x += (this.aclTo.x - this.acl.x) / 20;
    this.acl.y += (this.aclTo.y - this.acl.y) / 20;
  }
  public updatePos() {
    this.vel.x += this.acl.x;
    this.current.x += this.vel.x;
    this.vel.y += this.acl.y;
    this.current.y += this.vel.y;
  }
  public remove() {
  }
}
@Options({ components: {

} })
export default class CanvasParabola extends Vue {
  public rect: DOMRect|null = null;
  public ctx: CanvasRenderingContext2D|null=null;
  public boxList: Box[] = [];
  private timer: number|null = null;

  public move(e: TouchEvent) {
    // console.log(this);
    for (let index = 0; index < Math.floor(Math.random() * 10 + 5); index++) {
      const box = new Box(e.touches[0].pageX, e.touches[0].pageY, this.ctx);
      this.boxList.push(box);
    }
    if (this.boxList.length >= 50) {
      this.boxList.splice(0, this.boxList.length - 50);
    }
    if (!this.timer) {
      this.play();
    };
  }
  public play() {
    // console.log(this.boxList.length);
    // 在下一次渲染之前清空之前的画布
    this.ctx!.clearRect(0, 0, this.ctx!.canvas.width, this.ctx!.canvas.height);

    // 拖尾效果的实现
    // this.ctx!.save();
    // this.ctx!.globalAlpha = 0.1;
    // this.ctx!.fillStyle = '#fff';
    // this.ctx!.fillRect(0, 0, this.ctx!.canvas.width, this.ctx!.canvas.height);
    // this.ctx!.restore();

    for (let index = 0; index < this.boxList.length; index++) {
      const item = this.boxList[index];
      item.render(this.ctx);
      if (item.current.x < 0 || item.current.x >  this.rect!.width
      || item.current.y >  this.rect!.height || item.current.y < 0 || item.alpha <= 0) {
        item.remove();
        this.boxList.splice(index, 1);
        index -= 1;
      }
    }

    // 下一次渲染之前检查是否还有粒子存在
    if (this.boxList.length > 0) {
      this.timer =  window.requestAnimationFrame(this.play);
    } else {
      this.timer = null;
      // 当所有的粒子都超出画布时清空
      this.ctx!.clearRect(0, 0, this.ctx!.canvas.width, this.ctx!.canvas.height);
    }
  }
  public mounted() {
    this.rect = (this.$el as HTMLDivElement).getBoundingClientRect();
    this.ctx = (this.$refs.parabolaRef as HTMLCanvasElement).getContext('2d');
  }
};
</script>

<style lang="postcss">
.canvasParabola{
  touch-action: none;
  position: relative;
  width: 100%;
  height: 100%;
  /* background-color: grey; */
  canvas{
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
  }
}
</style>
